package cn.fuzongyao.learning.android.crime15;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import androidx.annotation.Nullable;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

import cn.fuzongyao.learning.android.crime15.database.CrimeBaseHelper;
import cn.fuzongyao.learning.android.crime15.database.CrimeDbSchema;

public class CrimeLab {
    private static CrimeLab crimeLab;
    private SQLiteDatabase crimeDatabase;

    public static CrimeLab getInstance(Context context) {
        if (crimeLab == null) {
            crimeLab = new CrimeLab(context);
        }
        return crimeLab;
    }

    private CrimeLab(Context context) {
        context = context.getApplicationContext();
        crimeDatabase = new CrimeBaseHelper(context).getWritableDatabase();
    }

    public List<Crime> getCrimes() {
        return queryCrimes(null, null);
    }

    @Nullable
    public Crime getCrime(String id) {
        String whereClause = CrimeDbSchema.CrimeTable.Cols.ID + " = ? ";
        String[] whereArgs = new String[]{id};
        List<Crime> crimes = queryCrimes(whereClause, whereArgs);
        return crimes.isEmpty() ? null : crimes.get(0);
    }

    public static int indexOf(List<Crime> crimes, String id) {
        for (int i = 0; i < crimes.size(); i++) {
            if (crimes.get(i).getId().equals(id)) {
                return i;
            }
        }
        return -1;
    }

    private List<Crime> queryCrimes(String whereClause, String[] whereArgs) {
        Cursor cursor = crimeDatabase.query(CrimeDbSchema.CrimeTable.NAME, null, whereClause, whereArgs, null, null, null);
        List<Crime> crimes = new ArrayList<>(cursor.getCount());
        try {
            while (cursor.moveToNext()) {
                crimes.add(getCrime(cursor));
            }
        } finally {
            cursor.close();
        }
        return crimes;
    }

    public void add(Crime crime) {
        crimeDatabase.insert(CrimeDbSchema.CrimeTable.NAME, null, getContentValues(crime));
    }

    public void update(Crime crime) {
        String whereClause = CrimeDbSchema.CrimeTable.Cols.ID + " = ? ";
        String[] whereArgs = new String[]{crime.getId()};
        crimeDatabase.update(CrimeDbSchema.CrimeTable.NAME, getContentValues(crime), whereClause, whereArgs);
    }

    public void remove(String id) {
        String whereClause = CrimeDbSchema.CrimeTable.Cols.ID + " = ? ";
        String[] whereArgs = new String[]{id};
        crimeDatabase.delete(CrimeDbSchema.CrimeTable.NAME, whereClause, whereArgs);
    }

    private static ContentValues getContentValues(Crime crime) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(CrimeDbSchema.CrimeTable.Cols.ID, crime.getId());
        contentValues.put(CrimeDbSchema.CrimeTable.Cols.TITLE, crime.getTitle());
        contentValues.put(CrimeDbSchema.CrimeTable.Cols.DATE, crime.getDate().atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli());
        contentValues.put(CrimeDbSchema.CrimeTable.Cols.SOLVED, crime.isSolved() ? 1 : 0);
        contentValues.put(CrimeDbSchema.CrimeTable.Cols.CONTACT_ID, crime.getContactId());
        contentValues.put(CrimeDbSchema.CrimeTable.Cols.SUSPECT, crime.getSuspect());
        contentValues.put(CrimeDbSchema.CrimeTable.Cols.MOBILE, crime.getMobile());
        return contentValues;
    }

    private Crime getCrime(Cursor cursor) {
        String id = cursor.getString(cursor.getColumnIndex(CrimeDbSchema.CrimeTable.Cols.ID));
        String title = cursor.getString(cursor.getColumnIndex(CrimeDbSchema.CrimeTable.Cols.TITLE));
        long timestamp = cursor.getLong(cursor.getColumnIndex(CrimeDbSchema.CrimeTable.Cols.DATE));
        LocalDate date = Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDate();
        int solved = cursor.getInt(cursor.getColumnIndex(CrimeDbSchema.CrimeTable.Cols.SOLVED));
        String contactIdString = cursor.getString(cursor.getColumnIndex(CrimeDbSchema.CrimeTable.Cols.CONTACT_ID));
        Integer contactId = contactIdString == null ? null : Integer.valueOf(contactIdString);
        String suspect = cursor.getString(cursor.getColumnIndex(CrimeDbSchema.CrimeTable.Cols.SUSPECT));
        String mobile = cursor.getString(cursor.getColumnIndex(CrimeDbSchema.CrimeTable.Cols.MOBILE));

        return new Crime().setId(id).setTitle(title).setDate(date).setSolved(solved != 0)
                .setContactId(contactId).setSuspect(suspect).setMobile(mobile);
    }
}
